package com.aysafety.iotdataplatformweb.services.electromagnetic.impl;

import com.aysafety.core.DBDriver.hbase.HBaseDriver;
import com.aysafety.core.common.DateUtils;
import com.aysafety.iotdataplatformweb.dao.ElectromagneticDao;
import com.aysafety.iotdataplatformweb.services.electromagnetic.ElectromagneticService;
import com.safety.algorithm.eigenvalue.EigenvalueAlgorithm;
import com.safety.algorithm.eigenvalue.soundEmission.SoundEmissionAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ElectromagneticServiceImpl implements ElectromagneticService {


    private final Map<String, Object> calMap = new HashMap<String, Object>() {
        {
            put("entId", "String");
            put("workingFace", "String");
            put("calType", "Integer");
            put("electromagneticWarningIndicator", "Double");
            put("hoursDeviation", "Double");
            put("flag", "Integer");
            put("datetime", "Date");
            put("dt", "Integer");
            put("m", "Integer");
            put("n", "Integer");
            put("a", "Double");
        }
    };

    @Autowired
    ElectromagneticDao electromagneticDao;

    @Override public long countByElectromagneticIntensity(String mineId, String deviceId, String startTime, String endTime,
                                                int timeSpan, String timeUnit) throws Throwable {
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "ElectromagneticIntensityRealTime");
        parram.put("entId", "\'" +mineId+ "\'");
        parram.put("deviceId", "\'" +deviceId+ "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        return electromagneticDao.countByElectromagneticIntensity(parram);
    }

    @Override public List<Map<String, Object>> queryRealTimeByElectromagneticIntensity(String mineId, String deviceId,
        String startTime, String endTime, int timeSpan, String timeUnit, int page, int size, String startRow)
        throws Throwable {

        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "ElectromagneticIntensityRealTime");
        parram.put("entId", "\'" +mineId+ "\'");
        parram.put("deviceId", "\'" +deviceId+ "\'");
        parram.put("startTime",startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        //parram.put("size", size);

        List<Map<String,Object>> result = electromagneticDao.queryRealTimeByElectromagneticIntensity(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime",DateUtils.getTime(dateTime));
            result.get(i).put("rowkey",result.get(i).get("PK"));
            result.get(i).remove("PK");
        }
        return result;
    }

    @Override public long countByElectromagneticPulse(String mineId, String deviceId, String startTime, String endTime,
                                            int timeSpan, String timeUnit) throws Throwable {
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "ElectromagneticPulseRealTime");
        parram.put("entId", "\'" +mineId+ "\'");
        parram.put("deviceId", "\'" +deviceId+ "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        return electromagneticDao.countByElectromagneticPulse(parram);

    }

    @Override public List<Map<String, Object>> queryRealTimeByElectromagneticPulse(String mineId, String deviceId,
                                                                         String startTime, String endTime, int timeSpan, String timeUnit, int page, int size, String startRow)
            throws Throwable {

        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "ElectromagneticPulseRealTime");
        parram.put("entId", "\'" +mineId+ "\'");
        parram.put("deviceId", "\'" +deviceId+ "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        //parram.put("size", size);

        List<Map<String,Object>> result = electromagneticDao.queryRealTimeByElectromagneticPulse(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime",DateUtils.getTime(dateTime));
            result.get(i).put("rowkey",result.get(i).get("PK"));
            result.get(i).remove("PK");
        }
        return result;
    }

    /**
     * @Description: web调用接口-电磁辐射趋势预警指标A数量
     * @Param: [mineId, workingFace, startTime, endTime, m, dt]
     * @return: long
     * @Author: ChengQi
     * @Date: 2018/12/20
     */
    @Override public long countWebElectromagneticRadiationWarning(String mineId, String workingFace, String startTime, String endTime, int m, int dt) throws Throwable {
        List<Map<String, Object>> conditions = new ArrayList<Map<String, Object>>();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warningIndicator");
        parram.put("columnId", "entId");
        parram.put("valueType", "String");
        parram.put("value", mineId);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warningIndicator");
        parram.put("columnId", "workingFace");
        parram.put("valueType", "String");
        parram.put("value", workingFace);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        /*parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warningIndicator");
        parram.put("columnId", "m");
        parram.put("valueType", "Integer");
        parram.put("value", m);
        parram.put("symbol", "EQUAL");
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warningIndicator");
        parram.put("columnId", "dt");
        parram.put("valueType", "Integer");
        parram.put("value", dt);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);*/
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warningIndicator");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", DateUtils.fomatDateTime(startTime).getTime());
        parram.put("symbol", "GREATER_OR_EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warningIndicator");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", com.aysafety.core.common.DateUtils.fomatDateTime(endTime).getTime());
        parram.put("symbol", "LESS_OR_EQUAL");
        conditions.add(parram);
        String startRow = "";
        String endRow = "";
        if (StringUtils.isNotBlank(startTime) && StringUtils.isBlank(startRow)) {
            endRow = String.valueOf(DateUtils.fomatDateTime(startTime).getTime()) + ".";
        }
        if (StringUtils.isNotBlank(endTime)) {
            startRow = String.valueOf(DateUtils.fomatDateTime(endTime).getTime()) + ".";
        }
        return HBaseDriver.countData("CalElectromagneticIntensity", conditions, startRow, endRow);
    }


    /**
     * @Description: web调用接口-电磁辐射趋势预警指标A数据
     * @Param: [mineId, workingFace, startTime, endTime, m, dt, page, size, startRow]
     * @return: java.util.List<java.util.Map               <               java.lang.String               ,               java.lang.Object>>
     * @Author: ChengQi
     * @Date: 2018/12/20
     */
    @Override public List<Map<String, Object>> queryCal(String mineId, String workingFace, String startTime, String endTime, int n,int m, int dt,int a) throws Throwable {


        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "CalElectromagneticIntensity");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("workingFace", "\'" + workingFace + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        List<Map<String, Object>> result = electromagneticDao.queryCal(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime", DateUtils.getTime(dateTime));
            result.get(i).put("rowkey", result.get(i).get("PK"));
            result.get(i).remove("PK");
        }
        return result;
    }

    @Override
    public long countWebDeviation(String mineId, String workingFace, String startTime, String endTime, int m, int dt, int n) throws Throwable {
        List<Map<String, Object>> conditions = new ArrayList<Map<String, Object>>();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "entId");
        parram.put("valueType", "String");
        parram.put("value", mineId);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "workingFace");
        parram.put("valueType", "String");
        parram.put("value", workingFace);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        /*parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "m");
        parram.put("valueType", "Integer");
        parram.put("value", m);
        parram.put("symbol", "EQUAL");
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "dt");
        parram.put("valueType", "Integer");
        parram.put("value", dt);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "n");
        parram.put("valueType", "Integer");
        parram.put("value", n);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);*/
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", DateUtils.fomatDateTime(startTime).getTime());
        parram.put("symbol", "GREATER_OR_EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", com.aysafety.core.common.DateUtils.fomatDateTime(endTime).getTime());
        parram.put("symbol", "LESS_OR_EQUAL");
        conditions.add(parram);
        String startRow = "";
        String endRow = "";
        if (StringUtils.isNotBlank(startTime) && StringUtils.isBlank(startRow)) {
            endRow = String.valueOf(DateUtils.fomatDateTime(startTime).getTime()) + ".";
        }
        if (StringUtils.isNotBlank(endTime)) {
            startRow = String.valueOf(DateUtils.fomatDateTime(endTime).getTime()) + ".";
        }
        return HBaseDriver.countData("CalElectromagneticIntensity", conditions, startRow, endRow);
    }

    @Override
    public List<Map<String, Object>> queryWebDeviation(String mineId, String workingFace, String startTime, String endTime, int m, int dt, int n) throws Throwable {
        List<Map<String, Object>> conditions = new ArrayList<Map<String, Object>>();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "entId");
        parram.put("valueType", "String");
        parram.put("value", mineId);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "workingFace");
        parram.put("valueType", "String");
        parram.put("value", workingFace);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        /*parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "m");
        parram.put("valueType", "Integer");
        parram.put("value", m);
        parram.put("symbol", "EQUAL");
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "dt");
        parram.put("valueType", "Integer");
        parram.put("value", dt);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "n");
        parram.put("valueType", "Integer");
        parram.put("value", n);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);*/
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", DateUtils.fomatDateTime(startTime).getTime());
        parram.put("symbol", "GREATER_OR_EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "deviation");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", com.aysafety.core.common.DateUtils.fomatDateTime(endTime).getTime());
        parram.put("symbol", "LESS_OR_EQUAL");
        conditions.add(parram);
        String startRow = "";
        String endRow = "";
        if (StringUtils.isNotBlank(startTime) && StringUtils.isBlank(startRow)) {
            endRow = String.valueOf(DateUtils.fomatDateTime(startTime).getTime()) + ".";
        }
        if (StringUtils.isNotBlank(endTime)) {
            startRow = String.valueOf(DateUtils.fomatDateTime(endTime).getTime()) + ".";
        }
        return HBaseDriver.queryData("CalElectromagneticIntensity", conditions, -1, 100000, this.calMap, startRow, endRow);
    }

    @Override
    public long deviationLast(String mineId, String workingFace, String startTime, String endTime, int m, int dt, int n) {
        return 0;
    }

    @Override
    public List<Map<String, Object>> querydeviationLast(String mineId, String workingFace, String startTime, String endTime, int m, int dt, int n,double a) throws Throwable {
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "CalElectromagneticIntensity");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("workingFace", "\'" + workingFace + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        List<Map<String, Object>> result = electromagneticDao.queryCal(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime", DateUtils.getTime(dateTime));
            result.get(i).put("rowkey", result.get(i).get("PK"));
            result.get(i).remove("PK");
        }
        List<Map<String, Object>> newlist = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < result.size(); i++) {
            if (i % 3 == 0) {
                newlist.add(result.get(i));
            }
        }
        return SoundEmissionAlgorithm.devAbnormal(newlist, n / m, m);
    }

    @Override
    public List<Map<String, Object>> deviationLastTotal(String mineId, String workingFace, String startTime, String endTime, int m, int dt, int n, double a) throws Throwable {
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "CalElectromagneticIntensity");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("workingFace", "\'" + workingFace + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        List<Map<String, Object>> result = electromagneticDao.queryCal(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime", DateUtils.getTime(dateTime));
            result.get(i).put("rowkey", result.get(i).get("PK"));
            result.get(i).remove("PK");
        }
        List<Map<String, Object>> newlist = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < result.size(); i++) {
            if (i % 3 == 0) {
                newlist.add(result.get(i));
            }
        }
        return SoundEmissionAlgorithm.devAbnormalTotal(newlist, n / m, m);
    }

    @Override
    public List<Map<String, Object>> deviationFrequency(String mineId, String workingFace, String startTime, String endTime, int m, int dt, int n,double a) throws Throwable {
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "CalElectromagneticIntensity");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("workingFace", "\'" + workingFace + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        List<Map<String, Object>> result = electromagneticDao.queryCal(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime", DateUtils.getTime(dateTime));
            result.get(i).put("rowkey", result.get(i).get("PK"));
            result.get(i).remove("PK");
        }
        List<Map<String, Object>> newlist = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < result.size(); i++) {
            if (i % 3 == 0) {
                newlist.add(result.get(i));
            }
        }
        return SoundEmissionAlgorithm.devAbnormalFrequency(newlist, n / m);
    }

    @Override public Map<String, Object> comprehensiveWarning(String mineId, String startTime, String endTime)
        throws Throwable {
        String startRow = "";
        String endRow = "";

        startTime = DateUtils.getBeforeDayDate(-30, startTime, "yyyy-MM-dd HH:mm:ss");

        List<Map<String, Object>> conditions = new ArrayList<Map<String, Object>>();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warning");
        parram.put("columnId", "entId");
        parram.put("valueType", "String");
        parram.put("value", mineId);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warning");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", DateUtils.fomatDateTime(startTime).getTime());
        parram.put("symbol", "GREATER_OR_EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warning");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", DateUtils.fomatDateTime(endTime).getTime());
        parram.put("symbol", "LESS_OR_EQUAL");
        conditions.add(parram);

        if (StringUtils.isNotBlank(startTime) && StringUtils.isBlank(startRow)) {
            endRow = String.valueOf(DateUtils.fomatDateTime(startTime).getTime());
        }
        if (StringUtils.isNotBlank(endTime)) {
            startRow = String.valueOf(DateUtils.fomatDateTime(endTime).getTime());
        }

        List<Map<String, Object>> result =
            HBaseDriver.queryData("CalWarningElectromagneticIntensity", conditions, -1, 100000, this.warning, startRow, endRow);

        double sumWi = 0.0;
        double sumRi = 0.0;
        double maxR = 0.0;
        double maxW = 0.0;
        for (int i = 0; i < result.size(); i++) {
            sumWi+=Double.parseDouble(result.get(i).get("w1").toString());
            sumRi+=Double.parseDouble(result.get(i).get("fitness").toString());
            maxR = maxR>Double.parseDouble(result.get(i).get("fitness").toString())?maxR:Double.parseDouble(result.get(i).get("fitness").toString());
            maxW = maxW>Double.parseDouble(result.get(i).get("w1").toString())?maxW:Double.parseDouble(result.get(i).get("w1").toString());
        }
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("R",maxR);
        map.put("W", EigenvalueAlgorithm.divide(sumWi*maxR,sumRi*maxW,0));
        map.put("result",result);
        return map;
    }

    private final Map<String, Object> warning = new HashMap<String, Object>() {
        {
            put("entId", "String");
            put("w1", "Double");
            put("fitness", "Double");
            put("datetime", "Date");
            put("last", "String");
        }
    };

}
